package com.maxlen.goods.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maxlen.common.utils.PageUtils;
import com.maxlen.common.utils.R;
import com.maxlen.goods.dao.AttrGroupDao;
import com.maxlen.goods.dao.SkuInfoDao;
import com.maxlen.goods.dao.SkuSaleAttrValueDao;
import com.maxlen.goods.entity.SkuImagesEntity;
import com.maxlen.goods.entity.SkuInfoEntity;
import com.maxlen.goods.entity.SpuInfoDescEntity;
import com.maxlen.goods.entity.SpuInfoEntity;
import com.maxlen.goods.entity.dto.SearchHomeDTO;
import com.maxlen.goods.entity.to.SkuPriceTO;
import com.maxlen.goods.entity.to.SpuAndSkuTO;
import com.maxlen.goods.entity.vo.SkuInfoPageParamsVO;
import com.maxlen.goods.entity.dto.SkuItemDTO;
import com.maxlen.goods.feign.SearchFeignService;
import com.maxlen.goods.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Service("skuInfoService")
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService {

    @Autowired
    private AttrGroupDao attrGroupDao;

    @Autowired
    private SkuImagesService skuImagesService;

    @Autowired
    private SpuInfoDescService spuInfoDescService;

    @Lazy
    @Autowired
    private SpuInfoService spuInfoService;

    @Autowired
    private SkuSaleAttrValueDao skuSaleAttrValueDao;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private SearchFeignService searchFeignService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private CategoryBrandRelationService categoryBrandRelationService;

    @Override
    public PageUtils queryPage(SkuInfoPageParamsVO params) {

        System.out.println(params);

        LambdaQueryWrapper<SkuInfoEntity> wrapper = new LambdaQueryWrapper<>();

        String key = params.getKey();
        if(StringUtils.hasText(key)){
            wrapper.like(SkuInfoEntity::getSkuName, key);
        }

        String brandId = params.getBrandId();
        if(StringUtils.hasText(brandId) && !"0".equals(brandId)){
            wrapper.eq(SkuInfoEntity::getBrandId, brandId);
        }

        String catelogId = params.getCatelogId();
        if(StringUtils.hasText(catelogId) && !"0".equals(catelogId)){
            wrapper.eq(SkuInfoEntity::getCatalogId, catelogId);
        }

        String min = params.getMin();
        if(StringUtils.hasText(min)){
            wrapper.ge(SkuInfoEntity::getPrice, min);
        }

        String max = params.getMax();
        if(StringUtils.hasText(max) && "0".equals(max) && new BigDecimal(max).compareTo(new BigDecimal("0")) == 1){
            wrapper.le(SkuInfoEntity::getPrice, max);
        }

        IPage<SkuInfoEntity> page = this.page(
                new Page<>(params.getPage(), params.getLimit()),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public void saveDetail(SkuInfoEntity skuInfoEntity) {
        baseMapper.insert(skuInfoEntity);
    }

    @Override
    public List<SkuInfoEntity> getSkusBySpuId(Long spuId) {
        return baseMapper.selectList(new LambdaQueryWrapper<SkuInfoEntity>().eq(SkuInfoEntity::getSpuId, spuId));
    }

    /**
     * 通过 skuId 获取商品详情页的所有信息
     * @param skuId
     * @return
     */
    @Override
    public SkuItemDTO getSkuInfo(Long skuId) throws ExecutionException, InterruptedException {

        SkuItemDTO skuItemDTO = new SkuItemDTO();

        // sku 基本信息
        CompletableFuture<SkuInfoEntity> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
            SkuInfoEntity skuInfo = getById(skuId);
            skuItemDTO.setInfo(skuInfo);
            return skuInfo;
        }, threadPoolExecutor);

        // sku 图片
        CompletableFuture<Void> skuImagesFuture = CompletableFuture.runAsync(() -> {
            List<SkuImagesEntity> skuImagesEntityList = skuImagesService.getImagesBySkuId(skuId);
            skuItemDTO.setImages(skuImagesEntityList);
        }, threadPoolExecutor);


        // spu 销售属性
        CompletableFuture<Void> spuSaleAttrFuture = skuInfoFuture.thenAcceptAsync((result) -> {
            List<SkuItemDTO.SkuItemSaleAttrDTO> skuItemSaleAttrVoList = skuSaleAttrValueDao.getBySpuId(result.getSpuId());
            skuItemDTO.setSaleAttr(skuItemSaleAttrVoList);
        }, threadPoolExecutor);


        // spu 介绍
        CompletableFuture<Void> spuDescFuture = skuInfoFuture.thenAcceptAsync((result) -> {
            SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(result.getSpuId());
            skuItemDTO.setDesc(spuInfoDescEntity);
        }, threadPoolExecutor);

        // spu 重量
        CompletableFuture<Void> spuWeightFuture = skuInfoFuture.thenAcceptAsync((result) -> {
            BigDecimal weight = spuInfoService.getWeightById(result.getSpuId());
            skuItemDTO.setWeight(weight);
        }, threadPoolExecutor);

        // spu 规格参数
        CompletableFuture<Void> spuBaseAttrFuture = skuInfoFuture.thenAcceptAsync((result) -> {
            List<SkuItemDTO.SpuItemAttrGroupDTO> spuItemAttrGroupVo = attrGroupDao.getAttrGroupWithAttrsBySpuIdAndCategoryId(result.getSpuId(), result.getCatalogId());
            skuItemDTO.setGroupVo(spuItemAttrGroupVo);
        }, threadPoolExecutor);

        CompletableFuture<Void> categoryFuture = skuInfoFuture.thenAcceptAsync((result) -> {
            List<SkuItemDTO.CategoryDetailDTO> categoryDetailDTO =  categoryService.getCategoryByIdWithAll(result.getCatalogId());
            skuItemDTO.setCategory(categoryDetailDTO);
        }, threadPoolExecutor);

        CompletableFuture<Void> brandFuture = skuInfoFuture.thenAcceptAsync((result) -> {
            List<SkuItemDTO.BrandDetailDTO> brand =  categoryBrandRelationService.getBrandByCatalogId(result.getCatalogId());
            skuItemDTO.setBrand(brand);
        }, threadPoolExecutor);


        CompletableFuture.allOf(skuImagesFuture, spuSaleAttrFuture, spuDescFuture, spuWeightFuture, spuBaseAttrFuture, categoryFuture, brandFuture).get();

        return skuItemDTO;
    }

    @Override
    public R getSkuInfoHome() {
        R searchHome = searchFeignService.searchHome();
        if(searchHome.isOk()){
            return searchHome;
        }else{
            return R.error();
        }
    }

    @Override
    public List<SkuPriceTO> getSkuPriceBySkuIdList(List<Long> skuIdList) {
        List<SkuInfoEntity> skuInfoEntityList = baseMapper.selectBatchIds(skuIdList);
        List<SkuPriceTO> skuPriceTOList = new ArrayList<>();
        SkuPriceTO skuPriceTO;
        for (SkuInfoEntity skuInfo : skuInfoEntityList) {
            skuPriceTO = new SkuPriceTO();
            skuPriceTO.setSkuId(skuInfo.getSkuId());
            skuPriceTO.setPrice(skuInfo.getPrice());
            skuPriceTOList.add(skuPriceTO);
        }

        return skuPriceTOList;

    }

    @Override
    public SpuAndSkuTO getSpuBySkuIdList(List<Long> skuIdList) {

        SpuAndSkuTO spuAndSkuTO = new SpuAndSkuTO();

        List<SpuAndSkuTO.SkuBySpuIdTO> skuBySpuIdTOList = baseMapper.getSkuIdAndSpuId(skuIdList);
        spuAndSkuTO.setSkuBySpuIdTO(skuBySpuIdTOList);

        List<Long> longList = skuBySpuIdTOList.stream().map((item) -> {
            return item.getSpuId();
        }).collect(Collectors.toList());
        List<SpuInfoEntity> spuInfoEntityList = spuInfoService.getBaseMapper().selectBatchIds(longList);
        spuAndSkuTO.setSpuInfoEntity(spuInfoEntityList);

        return spuAndSkuTO;

    }

    @Override
    public List<SkuInfoEntity> getSkuInfoBySkuIdList(List<Long> skuIdList) {
        return baseMapper.selectBatchIds(skuIdList);

    }

}
